package com.demo.function.arthas;

import lombok.extern.slf4j.Slf4j;

import java.lang.management.ManagementFactory;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.TimeUnit;

/**
 * 通过arthas的检查jvm线程问题
 */
@Slf4j
public class WatchThreadPool {

    /**
     * 循环创建线程池，并且执行任务
     *
     * 检查方法：
     * jvm命令：查询THREAD的守护线程数量，如果守护线程不断增加，证明不断创建线程池
     * thread命令：查看是否不断创建线程池。如果有输出日志，通过日志也能看出，线程池名称不断在变化
     */
    public void loopCreateThreadPool() {
        while (true) {
            exec();
        }
    }

    /**
     * 创建一个线程池，从线程池获取线程执行
     *
     * 检查方法：
     * jvm命令：查询THREAD的守护线程数量，数量是不变的
     * thread命令：查看是否不断创建线程池。如果有输出日志，通过日志也能看出，线程池名称都是固定的
     * @throws InterruptedException 异常
     */
    public void execThread() throws InterruptedException {
        ExecutorService executorService = Executors.newWorkStealingPool(2);
        while (true) {
            CompletableFuture.supplyAsync(() -> {
                String name = ManagementFactory.getRuntimeMXBean().getName();
                log.info("异步线程执行任务，线程名：{}", name);
                return null;
            }, executorService);
            TimeUnit.SECONDS.sleep(1);
        }
    }

    private void exec() {
        ExecutorService executorService = Executors.newWorkStealingPool(2);
        CompletableFuture.supplyAsync(() -> {
            String name = ManagementFactory.getRuntimeMXBean().getName();
            log.info("异步线程执行任务，线程名：{}", name);
            try {
                TimeUnit.MINUTES.sleep(10);
            } catch (Exception e) {
                log.error("", e);
            }
            return null;
        }, executorService);
    }
}
